#pragma once
#define _USE_MATH_DEFINES
#include <string>
#include <iostream>
#include <complex>
#include <math.h>

#include "targetver.h"
#include <windows.h>

#include <stdio.h>
#include <tchar.h>
#include <string>
#include <time.h>

#include <mpi.h>
#include <omp.h>

using namespace std;

// Short dwarf's description.
#define DWARF_NAME (char*)"Spectral method, unmanaged hybrid kernel."

// Constants for output files's names
#define DWARF_NAME_OUTPUT (char*)"Dwarf.Unmanaged.Hybrid"
#define PROFILE_TXT (char*)".Profile.txt"
#define RESULT_TXT (char*)".Result.txt"

// Default size for buffer.
#define BUFFER_SIZE 1024
#define LENGTH_FOR_PRINT 9000


// Default size for buffer.
#define NUMBER_ROOT_PROCESS 0


//Parse the command line arguments and fill the reference parameters.
typedef int (__cdecl *DLLParseArguments)(
    int,                                    //Count of command line tokens.
    char**,                                 //Command line tokens.
    char**,                                 //Name of input text file.
    char**,                                 //Name of profile text file.
    char** );                               //Name of result file.

// Write the rules of command line structure.
typedef void (__cdecl *DLLUsage)(void);

// Start the time count.
typedef void (__cdecl *DLLStart)(void);

// Stop the time count.
typedef void (__cdecl *DLLStop)(double*);

class Solver
{
public:
    Solver();
    ~Solver();

    void init();
    void solve();

    int commSize;                                   // Rank of the process.
    int commRank;                                   // Count of processes.

    bool isRootThread;                              //true for master process


    int lengthForProc;                              //the loading of process

    int length;                                     //size of matrix
 
	//phase weights
	complex<double> *W;
	int Wlength;

    //the complex array
    complex<double> **complexArray;

private:
    void FFT(complex<double> *complexArray);        //1-dimension Fast Fourier Algorithm  
    void transpose(complex<double> **matrix);       //transposition of matrix
    int rev(int n, int bitsize);                    //binary inversion 
    void EvaluateRowsUsingMPI(complex<double> **matrix);
};

// Settings taken from command line and input file.
class Settings
{
public:
    Settings();
    ~Settings();

    void finish(Solver *solver);
    void start();
    int init(int argc, char** argv, Solver *solver);

private:

    // Input & output files.
    char* inputFile;
    char* profileFile;
    char* resultFile;

    int parseConfigFile(Solver* solver);            // Parse input file into solver's structures.
    void writeSettings(Solver *solver);             // Write settings.

};
